package com.powermgr.boringtest.service.impl;

import com.powermgr.boringtest.bean.Device;
import com.powermgr.boringtest.service.IDeviceService;
import com.powermgr.boringtest.utils.CmdUtils;
import com.powermgr.boringtest.utils.FileZipUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.annotation.PostConstruct;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
import java.util.*;

import static com.powermgr.boringtest.utils.ConfigUtils.*;

/**
 * DeviceServiceImpl
 *
 * @author qiuxiangdong
 * @date 2023/9/18 14:27
 */
@Service
@Log4j2
public class DeviceServiceImpl implements IDeviceService {
    private List<Device> devices;
    private int devicesNums = 0;

    @PostConstruct
    private void init(){
        log.info("初始化 DeviceServiceImpl.java ");
        log.info("删除sn目录");
        FileZipUtils.deleteFile(SN);
        devices = new ArrayList<>();
        List<String> devicesList = CmdUtils.runCmd("hdc list targets");
        assert devicesList != null;
        for (String sn : devicesList) {
            devicesNums ++;
            String locationId = "";
            CmdUtils.runCmd("hdc -t " + sn + " shell reboot loader");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            List<String> exeList = CmdUtils.runCmd(PR_TOOLS + File.separator + "rk3568.exe LD");
            assert exeList != null;
            for (String exe : exeList) {
                if (exe.contains("Mode=Loader")){
                    locationId = exe.split("=")[4].split("\t")[0];
                    CmdUtils.runCmd(PR_TOOLS + File.separator + "rk3568.exe -s " + locationId + " RD");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            log.info("发现设备：sn = " + sn + " locationId = " +locationId);
            FileZipUtils.createFile(SN + File.separator + sn);
            log.info("拷贝对应刷机脚本和用例框架");
            try {
                File file = new File(PR_CASE);
                if (file.exists()) {
                    FileUtils.copyDirectory(file,
                            new File(SN + File.separator + sn + File.separator + "case"));
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
             updateXML(SN + File.separator + sn + File.separator + "case" + File.separator
                            + "developertest" + File.separator + "config" + File.separator + "user_config.xml",
                    SN + File.separator + sn + File.separator + "case" + File.separator + "tests", sn);
             updateXML(SN + File.separator + sn + File.separator + "case" + File.separator
                            + "acts" + File.separator + "config" + File.separator + "user_config.xml",
                    SN + File.separator + sn + File.separator + "case" + File.separator + "acts"
                            + File.separator + "testcases", sn);
             updateXML(SN + File.separator + sn + File.separator + "case" + File.separator
                            + "hats" + File.separator + "config" + File.separator + "user_config.xml",
                    SN + File.separator + sn + File.separator + "case" + File.separator + "hats"
                            + File.separator + "testcases", sn);
             updateXML(SN + File.separator + sn + File.separator + "case" + File.separator
                            + "hats" + File.separator + "config" + File.separator + "user_config.xml",
                    SN + File.separator + sn + File.separator + "case" + File.separator + "dcts"
                            + File.separator + "testcases", sn);
            devices.add(new Device(sn, locationId));
        }
        log.info("pr执行列表临时目录");
        FileZipUtils.createFile(PR_3DAY);
        log.info("pr执行列表保存目录");
        FileZipUtils.createFile(PR_LIST);
        log.info("pr下载3天保存目录");
        FileZipUtils.createFile(PR_VERSION);
        FileZipUtils.createFile(PR_XTS);
        FileZipUtils.createFile(PR_TDD);
        log.info("测试报告下载目录");
        FileZipUtils.createFile(PR_REPORTS);
        log.info("master分支Daily下载目录");
        FileZipUtils.createFile(DAILY);
    }

    @Override
    public Optional<Device> findIdleDevice() {
        for (Device device : devices) {
            if (!device.isBusy()) {
                log.info("发现空闲设备：" + device.getSn());
                return Optional.of(device);
            }
        }
        return Optional.empty();
    }

    @Override
    public void setDeviceBusy(String sn) {
        for (Device device : devices) {
            if (device.getSn().equals(sn)){
                device.setBusy(true);
            }
        }
    }

    @Override
    public void setDeviceIdle(String sn) {
        for (Device device : devices) {
            if (device.getSn().equals(sn)){
                device.setBusy(false);
            }
        }
    }

    @Override
    public int getDeviceNums() {
        return devicesNums;
    }

    private static void updateXML(String xmlPath, String casePath, String sn) {
        try {
            File inputFile = new File(xmlPath);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(inputFile);
            doc.getDocumentElement().normalize();
            Element dirElement = (Element) doc.getElementsByTagName("dir").item(0);
            Element snElement = (Element) doc.getElementsByTagName("sn").item(0);
            dirElement.setTextContent(casePath);
            snElement.setTextContent(sn);
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File(xmlPath));
            transformer.transform(source, result);
            log.info(xmlPath + " 中的测试用例路径为：" + casePath);
        } catch (Exception e) {
            log.error(xmlPath + " 中的测试用例路径失败");
            log.error(e);
        }
    }
}
